<?php

class ControllerWxappWxPay extends Controller {

	private $_APPID = 'wx8cdac7431d56c5f4'; //小程序appid
    private $_APPSECRET = 'c9bbeea4e83a0d8489f165573dd6772a'; //小程序密钥
	private $_MCHID = '1321117101'; //商户号
	private $_KEY = 'jPWMptBEGSbzTL84V2ryaKINo6mgZDJY'; //商户key

	//获取微信OpenSession
    protected function  getOpenSession($code) {
        $url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.$this->_APPID.'&secret='.$this->_APPSECRET.'&js_code='.$code.'&grant_type=authorization_code';
        $ret = json_decode(file_get_contents($url));

		return $ret;
    }
	
	//获取微信支付必要信息
	public function getWxPayInfo(){

		$requestjson = file_get_contents('php://input');
		$data = json_decode($requestjson, true);

		$unifiedorder = $this->unifiedorder($data); //统一下单接口

		$result = array(
			'appId' => $this->_APPID, //appid
			'timeStamp' => "".time()."", //时间戳
			'nonceStr' => $this->nonceStr(), //随机字符串
			'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //数据包
			'signType' => 'MD5',
		);
		
		//签名 
		$result['paySign'] = $this->getSign($result);
		$json['result'] = $result;

		$this->response->setOutput(json_encode($json));

	}

	//统一下单接口 
	protected function unifiedorder($data){ 

		$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';

		$code = $data['code'];
		$out_trade_no = "BHZ".time().rand(100,999)."-".$data['out_trade_no']; 
		$total_fee = (float)$data['total_fee']*100; //金额单位为分

		$parameters = array( 
			'appid' => $this->_APPID, //小程序ID 
			'mch_id' => $this->_MCHID, //商户号 
			'nonce_str' => $this->nonceStr(), //随机字符串 
			'body' => $out_trade_no.'的描述', //描述 
			'out_trade_no'=> $out_trade_no, //微信支付发起的订单号
			'total_fee' => $total_fee, //金额单位为分
			'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], //终端IP 
			'notify_url' => 'http://m.bhz360.com/catalog/controller/wxapp/wxpay_notify.php', //通知地址 确保外网能正常访问 
			'openid' => $this->getOpenSession($code)->openid, //用户id 
			'trade_type' => 'JSAPI'//交易类型 
		);

		//统一下单签名 
		$parameters['sign'] = $this->getSign($parameters); 
		$xmlData = $this->arrayToXml($parameters); 
		$return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));

		return $return; 

	}

	protected function postXmlCurl($xml, $url, $second = 30){ 
		$ch = curl_init(); 
		//设置超时 
		curl_setopt($ch, CURLOPT_TIMEOUT, $second); 
		curl_setopt($ch, CURLOPT_URL, $url); 
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验 
		//设置header 
		curl_setopt($ch, CURLOPT_HEADER, FALSE); 
		//要求结果为字符串且输出到屏幕上 
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 
		//post提交方式 
		curl_setopt($ch, CURLOPT_POST, TRUE); 
		curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 
	  
	  
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20); 
		curl_setopt($ch, CURLOPT_TIMEOUT, 40); 
		set_time_limit(0); 
	   
		//运行curl 
		$data = curl_exec($ch); 
		//返回结果 
		if ($data) { 
			curl_close($ch); 
			return $data; 
		} else { 
			$error = curl_errno($ch); 
			curl_close($ch); 
			throw new WxPayException("curl出错，错误码:$error"); 
		} 
	} 	
		
	//数组转换成xml 
	protected function arrayToXml($arr){ 
		$xml = "<root>"; 
		foreach ($arr as $key => $val) { 
			if(is_array($val)) { 
				$xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">"; 
			} else { 
				$xml .= "<" . $key . ">" . $val . "</" . $key . ">"; 
			} 
		} 
		$xml .= "</root>"; 
		return $xml; 
	}  
	  
	//xml转换成数组 
	protected function xmlToArray($xml){ 
		//禁止引用外部xml实体  
		libxml_disable_entity_loader(true); 
	  
		$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);   
		$val = json_decode(json_encode($xmlstring), true); 
		return $val; 
	}

	//生成签名 
	protected function getSign($Obj){
		foreach ($Obj as $k => $v) { 
			$Parameters[$k] = $v; 
		} 
		
		//签名步骤一：按字典序排序参数 
		ksort($Parameters); 
		$String = $this->formatBizQueryParaMap($Parameters, false); 
		//签名步骤二：在string后加入KEY 
		$String = $String . "&key=" . $this->_KEY; 
		//签名步骤三：MD5加密 
		$String = md5($String); 
		//签名步骤四：所有字符转为大写 
		$result_ = strtoupper($String); 

		return $result_; 
	}

	//格式化参数，签名过程需要使用 
	protected function formatBizQueryParaMap($paraMap, $urlencode){
		$buff = ""; 
		ksort($paraMap); 
		foreach ($paraMap as $k => $v) { 
			if ($urlencode) { 
				$v = urlencode($v); 
			} 
			$buff .= $k . "=" . $v . "&"; 
		} 

		$reqPar; 
		if (strlen($buff) > 0) { 
			$reqPar = substr($buff, 0, strlen($buff) - 1); 
		}

		return $reqPar; 
	} 

	//随机32位字符串
    protected function nonceStr(){
        $result = '';
        $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
        for ($i=0;$i<32;$i++){
            $result .= $str[rand(0,48)];
        }
        return $result;
    }

}

?>